package org.ddevil.data;

import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;


/**
 * A Filter that only excepts objects if they match a regular expression.
 * <p>
 * Contains singleton instances for common validation expressions:
 * <ul>
 * <li>{@link #ALPHA_ONLY}</li>
 * <li>{@link #DIGIT_ONLY}</li>
 * <li>{@link #CONTAINS_DIGIT}</li>
 * <li>{@link #ANY_CHARACTERS}</li>
 * <li>{@link #NO_WILDCARDS}</li>
 * </ul>
 *
 * <p>
 * Note: if an invalid regular expression is passed then this filter falls back to just being a {@link StringFilter}
 * </p>
 *
 * @author Rich O'Connell
 */
public class RegexFilter implements Filter {

    /** anyhting that has only alpha characters */
    public static final RegexFilter ALPHA_ONLY = new RegexFilter("[a-zA-Z]+");

    /** anything that is only digits */
    public static final RegexFilter DIGIT_ONLY = new RegexFilter("[\\d]*");

    /** anything that is only digits, allows decimals */
    public static final RegexFilter DECIMAL_DIGIT_ONLY = new RegexFilter("[\\d]*\\.?[\\d]*");

    /** anything that contains at least one digit */
    public static final RegexFilter CONTAINS_DIGIT = new RegexFilter(".*[0-9]+.*");

    /** anything that is not blank is valid */
    public static final RegexFilter ANY_CHARACTERS = new RegexFilter(".+");

    /** No wildcards(*,%)  */
    public static final RegexFilter NO_WILDCARDS = new RegexFilter("[^%\\*]*");


    private Pattern pattern;
    private String regEx;
    private StringFilter backupPlan;

    /**
     *
     */
    public RegexFilter(String regEx) {
    	this(regEx, -69);
    
    	
    }
    
    public RegexFilter(String regEx, int flags){
    	this.regEx = regEx;
    	try {
	    	if (flags == -69) {
	    		this.pattern = Pattern.compile(regEx);    		
	    	}
	    	else {
	    		this.pattern = Pattern.compile(regEx, flags);
	    	}
	    	backupPlan = null;
    	}catch(PatternSyntaxException e) {
    		//fallback
    		backupPlan = new StringFilter(regEx);
    	}
    }

    /* (non-Javadoc)
     *
     */
    public boolean accept(Object arg) {
    	if (backupPlan != null) {
    		return backupPlan.accept(arg);
    	}
        boolean ret;

        //for the purposes of this filter null values == empty strings
        if(arg == null) arg = "";

        ret = pattern.matcher(arg.toString()).matches();

        return ret;
    }

    @Override
    public String toString() {
    	return regEx;
    }
}
